package com.cskaoyan.javase._1extends._8hidden;

/**
 * 首先，这一章节的名字叫做：“属性的隐藏”
 * 但实际上我们主要探究"对象名.成员变量名"的访问机制。
 * 除此之外,我们还会探究一个非常重要的问题:
 * 父类引用指向子类对象后,和子类引用指向子类对象,有什么区别?
 * 引用的类型不同,对对象的使用有什么影响?
 *
 * 在Java中，把
 * “创建子类对象，访问父子类同名成员变量会得出子类中的结果，而父类中的同名成员变量仍然存在”
 * 的代码现象，被称之为“属性的隐藏”。
 *
 * 为什么"属性隐藏"?
 * 属性之所以隐藏，究其原因是“对象名.成员变量名"的访问机制决定的，接下来我们就重点研究这个机制。
 *
 * 在研究 对象名点访问成员变量 机制时，我们主要探究两个方向：
 *      1.访问范围，对象名.访问成员变量，究竟能够访问到哪些成员变量呢？根据什么来决定？
 *      2.访问结果，用对象名.访问一个成员变量，结果是什么？根据什么来决定？
 *
 * 当然，既然要研究对象名.的访问机制，那么首先就要弄明白这个“对象名”的几种来源
 * 在存在继承的前提下，至少有以下几种：
 *      1.创建父类对象,用父类引用接收，用对象名点访问。
 *      2.创建子类对象,用子类引用接收，用对象名点访问。
 *      3.创建子类对象,用父类引用接收，用对象名点访问。
 *
 * 1.首先研究访问的范围
 *      1.创建父类对象,用父类引用接收，用对象名点访问。
 *          仅能够访问父类中的成员变量
 *
 *      2.创建子类对象,用子类引用接收，用对象名点访问。
 *          访问范围是父类 + 子类
 *
 *      3.创建子类对象,用父类引用接收，用对象名点访问。
 *          仅能够访问父类中的成员变量
 *
 *      对象名点成员变量，它的访问范围是由引用的数据类型来决定的。
 *          a.如果引用是父类类型，那么它的访问范围只有父类（和父类的父类）。
 *          b.如果引用是子类类型，那么它的访问范围是子类 + 父类（父类如果还有父类也算上）。
 *
 * 2.然后研究访问的结果:
 *      1.创建父类对象,用父类引用接收，用对象名点访问。
 *          访问结果是父类的
 *
 *      2.创建子类对象,用子类引用接收，用对象名点访问。
 *          访问结果是子类的
 *
 *      3.创建子类对象,用父类引用接收，用对象名点访问。
 *          访问结果是父类的
 *
 *      对象名点成员变量，访问的结果也是由 引用的数据类型 来决定的。
 *          1.如果引用是父类类型，那么它的访问结果一定也是父类中的结果。
 *          2.如果引用是子类类型，那么它的访问结果一定也是子类中的结果。
 *
 * 总结,换句话说,"对象名.成员变量",它的访问,以及访问结果,在程序的编译时期就决定了
 * 无需程序运行.
 *
 *
 * @since 09:46
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Son s = new Son();
        System.out.println(s.a);
        System.out.println(s.getA());*/

        // 1.创建父类对象,用父类引用接收，用对象名点访问。
        Father f = new Father();
        System.out.println(f.a);
        System.out.println(f.fatherA);

        // 2.创建子类对象,用子类引用接收，用对象名点访问。
        Son s = new Son();
        System.out.println(s.sonA);
        System.out.println(s.fatherA);
        System.out.println(s.a);

        // 3.创建子类对象,用父类引用接收，用对象名点访问。
        Father fs = new Son();
        // System.out.println(fs.fatherA);
        // System.out.println(fs.a);
        // 这时无法直接访问子类独有成员变量
        // ((Son) fs).sonA
        System.out.println(fs.a);

    }
}

class Father {
    int a = 10;
    int fatherA = 100;

    /*public int getA() {
        return a;
    }*/
}

class Son extends Father {
    int a = 20;
    int sonA = 200;

}